﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SQLite;

namespace WowRaidListTracker.DAL
{
    public class RaidMemberList : IComparable
    {
        public static Dictionary<object, RaidMemberListType> ListTypesDictionary = new Dictionary<object, RaidMemberListType>();
        public static List<RaidMemberListType> ListTypes = new List<RaidMemberListType>();

        public int TypeId
        {
            get;
            set;
        }

        public int CurrentRank
        {
            get;
            set;
        }

        public DateTime LastLootDate
        {
            get;
            set;
        }

        public string LastLootItem
        {
            get;
            set;
        }

        public int MemberId
        {
            get;
            set;
        }

        private RaidMember m_Member;
        public RaidMember Member
        {
            get
            {
                if (m_Member == null && MemberId > 0)
                {
                    m_Member = new RaidMember();
                    m_Member.LoadMember(MemberId);
                    return m_Member;
                }
                else
                {
                    return m_Member;
                }
            }
        }

        public RaidMemberList()
        {
        }

        public RaidMemberList(DataRow dr)
        {
            m_Member = new RaidMember();
            Load(dr);
        }

        public bool CreateList(List<RaidMemberList> members)
        {
            // loop through the passed collection and add each list item to the database
            foreach (RaidMemberList r in members)
            {
                AddItem(r);
            }
            return true;
        }

        public NonQueryResult AddItem()
        {
            return AddItem(this);
        }

        private NonQueryResult AddItem(RaidMemberList r)
        {
            ListTrackerDal data = new ListTrackerDal();
            CRUDReader qud = new CRUDReader();
            List<SQLiteParameter> parameters = new List<SQLiteParameter>();
            string insert = qud.get("InsertRaidListItem", CRUDReader.QUDType.Insert);
            parameters.Add(new SQLiteParameter("@TypeId", r.TypeId));
            parameters.Add(new SQLiteParameter("@Rank", r.CurrentRank));
            parameters.Add(new SQLiteParameter("@MemberId", r.MemberId));

            NonQueryResult nqr = (NonQueryResult)data.Execute(insert, SQLiteQueryType.NONSTANDARDQUERY, parameters);

            if (nqr.RowsAffected == 0)
                throw new Exception("The Member " + r.Member.Name + " could not be added to a list.");
            return nqr;
        }

        public NonQueryResult ReceiveLoot(string item)
        {
            ListTrackerDal dal = new ListTrackerDal();
            List<SQLiteParameter> parameters = new List<SQLiteParameter>();
            DateTime now = DateTime.Now;
            parameters.Add(new SQLiteParameter("@Date", now));
            parameters.Add(new SQLiteParameter("@LastItem", item));
            parameters.Add(new SQLiteParameter("@TypeId", TypeId));
            parameters.Add(new SQLiteParameter("@Id", Member.Id));
            NonQueryResult nqr = (NonQueryResult)dal.Execute(
                CRUDReader.Crud.get("UpdateRaidMemberListReceiveLoot", CRUDReader.QUDType.Update),
                SQLiteQueryType.NONSTANDARDQUERY,
                parameters
            );

            if (nqr.RowsAffected == 0)
                throw new Exception("The Member " + Member.Name + " could not be found.");

            LastLootDate = now;
            LastLootItem = item;

            return nqr;
        }

        public NonQueryResult UpdateRank(int newRank)
        {
            ListTrackerDal dal = new ListTrackerDal();
            List<SQLiteParameter> parameters = new List<SQLiteParameter>();
            parameters.Add(new SQLiteParameter("@Rank", newRank));
            parameters.Add(new SQLiteParameter("@Id", Member.Id));
            parameters.Add(new SQLiteParameter("@TypeId", TypeId));
            NonQueryResult nqr = (NonQueryResult)dal.Execute(
                CRUDReader.Crud.get("UpdateRaidMemberListRank", CRUDReader.QUDType.Update),
                SQLiteQueryType.NONSTANDARDQUERY,
                parameters
            );

            if (nqr.RowsAffected == 0)
                throw new Exception("The rank could not be updated.");

            CurrentRank = newRank;
            return nqr;
        }

        public NonQueryResult RemoveItem()
        {
            return RemoveItem(TypeId, MemberId);
        }

        public NonQueryResult RemoveItem(int typeId, int memberId)
        {
            ListTrackerDal data = new ListTrackerDal();
            CRUDReader qud = new CRUDReader();
            List<SQLiteParameter> parameters = new List<SQLiteParameter>();
            parameters.Add(new SQLiteParameter("@MemberId", memberId));
            parameters.Add(new SQLiteParameter("@TypeId", typeId));
            NonQueryResult nqr = (NonQueryResult)data.Execute(
                qud.get("RemoveRaidMemberListItem", CRUDReader.QUDType.Delete),
                SQLiteQueryType.NONSTANDARDQUERY,
                parameters
            );
            return nqr;
        }

        public NonQueryResult RemoveItem(int memberId)
        {
            ListTrackerDal data = new ListTrackerDal();
            CRUDReader qud = new CRUDReader();
            List<SQLiteParameter> parameters = new List<SQLiteParameter>();
            parameters.Add(new SQLiteParameter("@MemberId", memberId));
            NonQueryResult nqr = (NonQueryResult)data.Execute(
                qud.get("RemoveRaidMemberListMember", CRUDReader.QUDType.Delete),
                SQLiteQueryType.NONSTANDARDQUERY,
                parameters
            );
            return nqr;
        }

        public NonQueryResult UpdateRank()
        {
            return UpdateRank(CurrentRank);
        }

        private void Load(DataRow dr)
        {
            TypeId = Convert.ToInt32(dr["RaidMemberListTypeId"]);
            CurrentRank = Convert.ToInt32(dr["RaidMemberListCurrentRank"]);
            if (dr["RaidMemberListLastLootDate"].GetType() == typeof(DBNull))
            {
                LastLootDate = DateTime.Parse("1/1/1900 12:00:00 AM");
            }
            else
            {
                LastLootDate = Convert.ToDateTime(dr["RaidMemberListLastLootDate"]);
            }
            LastLootItem = Convert.ToString(dr["RaidMemberListLastLootItem"]);
            MemberId = Convert.ToInt32(dr["RaidMemberId"]);
            m_Member.LoadMember(MemberId);
        }

        public static void LoadTypes()
        {
            ListTrackerDal dal = new ListTrackerDal();
            DataTable dt = (DataTable)dal.Execute(
                CRUDReader.Crud.get("RaidMemberListTypes", CRUDReader.QUDType.Select),
                SQLiteQueryType.STANDARDQUERY
            );
            ListTypes.Add(new RaidMemberListType()
            {
                TypeId = -1,
                Name = "Select List..."
            });
            foreach (DataRow dr in dt.Rows)
            {
                RaidMemberListType rlt = new RaidMemberListType(dr);
                ListTypesDictionary.Add(rlt.Name, rlt);
                ListTypesDictionary.Add(rlt.TypeId, rlt);
                ListTypes.Add(rlt);
            }
        }

        public class RaidMemberListType
        {
            public int TypeId
            {
                get;
                set;
            }

            public string Name
            {
                get;
                set;
            }

            public string Description
            {
                get;
                set;
            }

            public RaidMemberListType()
            {
            }

            public RaidMemberListType(DataRow dr)
            {
                TypeId = Convert.ToInt32(dr["RaidMemberListTypeId"]);
                Name = Convert.ToString(dr["RaidMemberListTypeName"]);
                Description = Convert.ToString(dr["RaidMemberListTypeDescription"]);
            }

            public static RaidMemberListTypes GetTypeBySpecialization(int specializationId)
            {
                RaidMemberListTypes type;
                switch (specializationId)
                {
                    case 1: // tank
                        type = RaidMemberListTypes.Tank;
                        break;
                    case 2: // MeleeDPS
                        type = RaidMemberListTypes.MeleeDPS;
                        break;
                    case 3: // Healer
                        type = RaidMemberListTypes.Healer;
                        break;
                    case 4: // CasterDPS
                        type = RaidMemberListTypes.CasterDPS;
                        break;
                    default: // None
                        type = RaidMemberListTypes.None;
                        break;
                }
                return type;
            }
        }

        #region IComparable Members

        public int CompareTo(object obj)
        {
            if (typeof(RaidMemberList) != obj.GetType())
                throw new ArgumentException("The passed object is not of the correct type");
            RaidMemberList r2 = obj as RaidMemberList;
            return CurrentRank.CompareTo(r2.CurrentRank);
        }

        #endregion
    }

    public enum RaidMemberListTypes
    {
        Tank = 1,
        MeleeDPS = 2,
        CasterDPS = 4,
        Healer = 5,
        Shards = 3,
        None = 0
    }
}
